/*
 * @Author: 李石
 * @Date: 2024-05-18 10:29:46
 * @LastEditors: lishi
 * @LastEditTime: 2024-05-22 19:59:42
 * @Description: 
 * Copyright (c) 2024 by ${lishi0105@163.com}, All Rights Reserved. 
 */
#include "logger.hpp"
#include "utilspp.hpp"
#include "HttpData.hpp"
#include "StreamDto.hpp"
#include "HttpDataHandler.hpp"

static const std::string replyHeader = std::string("Content-Type: application/json\r\n");
HttpDataHandler::HttpDataHandler():
    stream_service(StreamService::CreateShared())
{
    errno_map_ = {
        {200, "OK"},
        {201, "Created"},
        {202, "Accepted"},
        {203, "Non-Authoritative Information"},
        {204, "No Content"},
        {300, "Program run error"},
        {400, "Bad Request"},
        {404, "Not Found"},
        {500, "Internal Server Error"},
        {501, "Not Implemented"},
        {502, "Bad Gateway"},
        {503, "Service Unavailable"},
        {504, "Gateway Timeout"},
        {505, "HTTP Version Not Supported"}
    };
}

void HttpDataHandler::init()
{
    stream_service->init();
}

template<typename DtoType>
void HttpDataHandler::response_handler(struct mg_connection* connection, int code, std::shared_ptr<DtoType> dto)
{
    typename ResponseDto<DtoType>::Ptr response = ResponseDto<DtoType>::CreateShared();
    response->code = code;
    if(errno_map_.find(response->code) != errno_map_.end()){
        response->msg = errno_map_[code];
    }else{
        response->msg = errno_map_[300];
    }
    response->data = dto;
    mg_http_reply(connection, code, replyHeader.c_str(), "%s", response->ToString().c_str());
}

void HttpDataHandler::HandleAddStreamProxy(struct mg_connection* connection, struct mg_http_message* hm) {
    // Implement your logic to get the stream list
    StreamAddDto::Ptr dto = nullptr;
    if (connection == nullptr) {
        LOGE("HttpData::CreateShared: invalid input");
        return response_handler(connection, 400, dto);
    }
    HttpData::Ptr httpData = HttpData::CreateShared(connection, hm);
    if(!httpData->is_valid()){
        return response_handler(connection, 400, dto);
    }
    dto = StreamAddDto::Fetch(httpData->body());
    if(dto == nullptr){
        return response_handler(connection, 400, dto);
    }
    // 打印 StreamAddDto 对象的内容
    LOGI("app: ({}) stream: ({}) url: ({}) rtp_type: ({})", dto->app, dto->stream, dto->url, dto->rtp_type);
    std::string err = "";
    auto stream = stream_service->insertStream(dto, err);
    if(stream != nullptr){
        return response_handler(connection, 200, stream);
    }
    ErrMsgDto::Ptr errDto = ErrMsgDto::CreateShared();
    errDto->err = err;
    return response_handler(connection, 300, errDto);
}

void HttpDataHandler::HandleGetStreamList(struct mg_connection* connection, struct mg_http_message* hm)
{
    StreamListDto::Ptr list = nullptr;
    HttpData::Ptr httpData = HttpData::CreateShared(connection, hm);
    if(!httpData->is_valid()){
        return response_handler(connection, 400, list);
    }
    std::string err;
    list = stream_service->getStream(err);
    if(list == nullptr){
        ErrMsgDto::Ptr errDto = ErrMsgDto::CreateShared();
        errDto->err = err;
        return response_handler(connection, 300, errDto);
    }
    return response_handler(connection, 200, list);
}

void HttpDataHandler::HandleGetStreamInfo(struct mg_connection* connection, struct mg_http_message* hm)
{
    StreamIDDto::Ptr dto = nullptr;
    if (connection == nullptr) {
        LOGE("HttpData::CreateShared: invalid input");
        return response_handler(connection, 400, dto);
    }
    HttpData::Ptr httpData = HttpData::CreateShared(connection, hm);
    if(!httpData->is_valid()){
        return response_handler(connection, 400, dto);
    }
    dto = StreamIDDto::Fetch(httpData->body());
    if(dto == nullptr){
        return response_handler(connection, 400, dto);
    }
    std::string err;
    auto report = stream_service->getStream(dto, err);
    return response_handler(connection, 200, report);
}

void HttpDataHandler::HandleDeleteStreamProxy(struct mg_connection* connection, struct mg_http_message* hm)
{
    ErrMsgDto::Ptr errDto = nullptr;
    if (connection == nullptr) {
        LOGE("HttpData::CreateShared: invalid input");
        return response_handler(connection, 400, errDto);
    }
    HttpData::Ptr httpData = HttpData::CreateShared(connection, hm);
    if(!httpData->is_valid()){
        return response_handler(connection, 400, errDto);
    }
    auto dto = StreamIDDto::Fetch(httpData->body());
    if(dto == nullptr){
        return response_handler(connection, 400, errDto);
    }
    LOGI("app: ({}) stream: ({})", dto->app, dto->stream);
    std::string err;
    if(stream_service->removeStream(dto, err)){
        return response_handler(connection, 200, errDto);
    }
    errDto = ErrMsgDto::CreateShared();
    errDto->err = err;
    return response_handler(connection, 300, errDto);
}

void HttpDataHandler::HandleNotFound(struct mg_connection* connection, struct mg_http_message* hm)
{
    ErrMsgDto::Ptr errDto = nullptr;
    (void)hm;
    return response_handler(connection, 404, errDto);
}